//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package user_mail_api_serv

import (
	"context"
	"fmt"
	"strings"
	"time"

	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/mail_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_mail_api"
	"github.com/dchest/uniuri"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *UserMailApiImpl) CreateAccount(ctx context.Context, req *user_mail_api.CreateAccountRequest) (*user_mail_api.CreateAccountResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.CreateAccountResponse{
			Code:   user_mail_api.CreateAccountResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	count, err := mail_dao.AccountDao.Count(ctx, sessionItem.UserId)
	if err != nil {
		return nil, err
	}

	if count >= apiImpl.clientCfg.MaxMailCountPerUser {
		return &user_mail_api.CreateAccountResponse{
			Code:   user_mail_api.CreateAccountResponse_CODE_TOO_MANY_ACCOUNT,
			ErrMsg: "账号数超过限额",
		}, nil
	}

	accountPrefix := sessionItem.UserName
	pos := strings.Index(accountPrefix, "@")
	if pos != -1 {
		accountPrefix = accountPrefix[:pos]
	}
	pos = strings.Index(accountPrefix, ":")
	if pos != -1 {
		accountPrefix = accountPrefix[pos+1:]
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		for i := 0; i < 10; i++ {
			suffix := uniuri.NewLenChars(8, []byte("abcdefghijklmnopqrstuvwxyz"))
			account := fmt.Sprintf("%s_%s", accountPrefix, suffix)
			exist, err := mail_dao.AccountDao.Exist(sessCtx, sessionItem.UserId, account)
			if err != nil {
				return nil, err
			}
			if exist {
				continue
			}
			err = mail_dao.AccountDao.Insert(sessCtx, &mail_dao.MailAccountDbItem{
				Account:   account,
				UserId:    sessionItem.UserId,
				Remark:    "",
				TimeStamp: nowTime,
			})
			if err != nil {
				return nil, err
			}
			return &user_mail_api.CreateAccountResponse{
				Code:    user_mail_api.CreateAccountResponse_CODE_OK,
				Account: account,
			}, nil
		}
		return &user_mail_api.CreateAccountResponse{
			Code:   user_mail_api.CreateAccountResponse_CODE_TOO_MANY_ACCOUNT,
			ErrMsg: "无法添加账号",
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*user_mail_api.CreateAccountResponse), nil
}

func (apiImpl *UserMailApiImpl) UpdateAccount(ctx context.Context, req *user_mail_api.UpdateAccountRequest) (*user_mail_api.UpdateAccountResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.UpdateAccountResponse{
			Code:   user_mail_api.UpdateAccountResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	exist, err := mail_dao.AccountDao.Exist(ctx, sessionItem.UserId, req.Account)
	if err != nil {
		return nil, err
	}

	if !exist {
		return &user_mail_api.UpdateAccountResponse{
			Code:   user_mail_api.UpdateAccountResponse_CODE_NO_ACCOUNT,
			ErrMsg: "账号不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = mail_dao.AccountDao.UpdateRemark(sessCtx, sessionItem.UserId, req.Account, req.Remark, nowTime)
		if err != nil {
			return nil, err
		}
		return &user_mail_api.UpdateAccountResponse{
			Code: user_mail_api.UpdateAccountResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*user_mail_api.UpdateAccountResponse), nil
}

func (apiImpl *UserMailApiImpl) ListAccount(ctx context.Context, req *user_mail_api.ListAccountRequest) (*user_mail_api.ListAccountResponse, error) {
	emptyList := []*user_mail_api.MailAccount{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.ListAccountResponse{
			Code:        user_mail_api.ListAccountResponse_CODE_WRONG_SESSION,
			ErrMsg:      "会话不存在",
			AccountList: emptyList,
		}, nil
	}

	accountItemList, err := mail_dao.AccountDao.List(ctx, sessionItem.UserId)
	if err != nil {
		return nil, err
	}

	accountList := []*user_mail_api.MailAccount{}
	for _, accountItem := range accountItemList {
		accountList = append(accountList, accountItem.ToMailAccount())
	}

	return &user_mail_api.ListAccountResponse{
		Code:        user_mail_api.ListAccountResponse_CODE_OK,
		AccountList: accountList,
	}, nil
}

func (apiImpl *UserMailApiImpl) RemoveAccount(ctx context.Context, req *user_mail_api.RemoveAccountRequest) (*user_mail_api.RemoveAccountResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.RemoveAccountResponse{
			Code:   user_mail_api.RemoveAccountResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := mail_dao.AccountDao.Exist(ctx, sessionItem.UserId, req.Account)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &user_mail_api.RemoveAccountResponse{
			Code: user_mail_api.RemoveAccountResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = mail_dao.AccountDao.Remove(sessCtx, sessionItem.UserId, req.Account)
		if err != nil {
			return nil, err
		}
		return &user_mail_api.RemoveAccountResponse{
			Code: user_mail_api.RemoveAccountResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*user_mail_api.RemoveAccountResponse), nil
}
